package com.khstudio.api.bitmapcache;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;

import com.khstudio.api.util.KhLog;

public class KhBitmapLruCacheDisk implements KhBitmapLruCache {
    private static final CompressFormat COMPRESSFORMAT  = CompressFormat.JPEG;
    private static final int            COMPRESSQUALITY = 100;

    private KhDiskLruCache mDiskCache;
    private CompressFormat mCompressFormat = CompressFormat.JPEG;
    private int mCompressQuality = 100;
    private static final int APP_VERSION = 1;
    private static final int VALUE_COUNT = 1;

    public KhBitmapLruCacheDisk(Context context,String uniqueName, int diskCacheSize) {
        this(context, uniqueName, diskCacheSize, COMPRESSFORMAT, COMPRESSQUALITY);
    }

    public KhBitmapLruCacheDisk( Context context,String uniqueName, int diskCacheSize,
        CompressFormat compressFormat, int quality ) {
        try {
            final File diskCacheDir = getDiskCacheDir(context, uniqueName );
            mDiskCache = KhDiskLruCache.open( diskCacheDir, APP_VERSION, VALUE_COUNT, diskCacheSize );
            mCompressFormat = compressFormat;
            mCompressQuality = quality;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private boolean writeBitmapToFile( Bitmap bitmap, KhDiskLruCache.Editor editor )
        throws IOException, FileNotFoundException {
        OutputStream out = null;
        try {
            out = new BufferedOutputStream( editor.newOutputStream( 0 ), KhUtil.IO_BUFFER_SIZE );
            return bitmap.compress( mCompressFormat, mCompressQuality, out );
        } finally {
            if ( out != null ) {
                out.close();
            }
        }
    }

    private File getDiskCacheDir(Context context, String uniqueName) {

    // Check if media is mounted or storage is built-in, if so, try and use external cache dir
    // otherwise use internal cache dir
        final String cachePath =
            Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||
                    !KhUtil.isExternalStorageRemovable() ?
                    KhUtil.getExternalCacheDir(context).getPath() :
                    context.getCacheDir().getPath();
//        KVideoCapture application = ((KVideoCapture) context.getApplicationContext());
//        final String cachePath = application.getStoragePath() + File.separator +String.valueOf("cache");

        return new File(cachePath + File.separator + uniqueName);
    }

    @Override
    public void put(String key, Bitmap data) {
        KhDiskLruCache.Editor editor = null;
        try {
            editor = mDiskCache.edit( key );
            if ( editor == null ) {
                return;
            }

            if( writeBitmapToFile( data, editor ) ) {
                mDiskCache.flush();
                editor.commit();
                KhLog.v("KhBitmapLruCacheDisk : image put on disk cache " + key);
            } else {
                editor.abort();
                KhLog.w("KhBitmapLruCacheDisk : ERROR 1 on: image put on disk cache " + key);
            }
        } catch (IOException e) {
        	KhLog.w("KhBitmapLruCacheDisk : ERROR 2 on: image put on disk cache " + key);
            try {
                if ( editor != null ) {
                    editor.abort();
                }
            } catch (IOException ignored) {
            }
        }

    }

    @Override
    public Bitmap get(String key) {
        Bitmap bitmap = null;
        KhDiskLruCache.Snapshot snapshot = null;
        try {

            snapshot = mDiskCache.get(key);
            if ( snapshot == null ) {
            	KhLog.w("KhBitmapLruCacheDisk : snapshot == null key = " + key);
                return null;
            }
            final InputStream in = snapshot.getInputStream( 0 );
            if ( in != null ) {
                final BufferedInputStream buffIn =
                new BufferedInputStream( in, KhUtil.IO_BUFFER_SIZE );
                bitmap = BitmapFactory.decodeStream( buffIn );
            }
        } catch ( IOException e ) {
            e.printStackTrace();
        } finally {
            if ( snapshot != null ) {
                snapshot.close();
            }
        }

        KhLog.v("KhBitmapLruCacheDisk : cache_test_DISK_", bitmap == null ? "" : "image read from disk " + key);

        return bitmap;
    }

    @Override
    public void remove(String key) {
        try {
            mDiskCache.remove(key);
        } catch ( IOException e ) {
            e.printStackTrace();
        }
    }

    @Override
    public void clear() {
    	KhLog.v("KhBitmapLruCacheDisk : disk cache CLEARED");
        try {
            mDiskCache.delete();
        } catch ( IOException e ) {
            e.printStackTrace();
        }
    }

}
